/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#ifndef __LIB3D_PARTICLE_H__
#define __LIB3D_PARTICLE_H__

#include <map>
#include <Atom.h>
#include <logs/Log.h>
#include <math/Vector2.h>
#include <math/Vector3.h>
#include <Color.h>
#include <lib3d/hard/Texture.h>
#include "ParticlesOptions.h"
#include <lib3d/Math_lib3d.h>

namespace liba
{
	namespace lib3d
	{
		namespace particles
		{
			class Particle
			{
			private:
				struct AdditionalField
				{
					void * data;
					void (*destructor)(void * data);
				};
			private:
				std::map<void*, AdditionalField> _additionalData;
			public:
				struct ParticleData
				{
					math::Vector3<Float> position;
					math::Vector2<Float> scale;
					Float                angle;
					Color                color;
					Float                alpha;
				};
			public:
				bool                 isAlive;
				Float                lifeTime;
				ParticleData         currentState;
				ParticleData         startState;
				
				math::Vector3<Float> baseVelocity;
				Float                baseVelocityFrame;
				math::Vector3<Float> nextVelocity;
				Float                nextVelocityFrame;
				
				Float                baseAlpha;
				Float                baseAlphaFrame;
				Float                nextAlpha;
				Float                nextAlphaFrame;
				
				Color                baseColor;
				Float                baseColorFrame;
				Color                nextColor;
				Float                nextColorFrame;
				
				math::Vector2<Float> baseSize;
				Float                baseSizeFrame;
				math::Vector2<Float> nextSize;
				Float                nextSizeFrame;
				
				Float                baseTorque;
				Float                baseTorqueFrame;
				Float                nextTorque;
				Float                nextTorqueFrame;
				
				Float                baseAngle;
				Float                baseAngleFrame;
				Float                nextAngle;
				Float                nextAngleFrame;
			public:
				Particle();
				~Particle();
				void clear();
				void save_state();
				void set_data_for_event(void * event, void * data, bool validate = true, void (*destructor)(void * data) = free);
				void remove_data_for_event(void * event);
				bool data_for_event_is_setted(void * event);
				void * get_data_for_event(void * event);
				
				template<typename DataType>
				DataType & get_data_for_event(void * event, bool createIfNeeded = true)
				{
					// getting pointer to data
					DataType * data = (DataType*)get_data_for_event(event);
					
					// check if it is valid
					if(data == NULL)
					{
						if(!createIfNeeded)
						{
							static DataType static_value = DataType();
							return static_value;
						}
						
						// create new object
						data = new DataType();
						set_data_for_event(event, data, false);
					}
					
					// return reference to data
					return *data;
				}
			};
		}
	}
}

using namespace liba;

#endif